/// <reference path="./Uri.ts" />
/// <reference path="./engine/Transport.ts" />
namespace egret.socketio {

    /**
     * IO
     */
    export interface Option extends ManagerOptions {
        forceNew?: boolean;
        multiplex?: boolean;
    }

    class IO {

        private static instance: IO;

        private _cache: { [name: string]: Manager } = {};

        public socket(uri?: Uri | string, opts?: Option): Socket {

            let uristr = typeof uri == 'string' ? uri : uri.toString();
            opts = opts || {};

            let parsed = new Uri(uristr);
            parsed.addTrailingSlash();

            let id = Url.extractId(uristr);
            let path = parsed.path;

            let sameNamespace = this._cache[id] && path in this._cache[id].nsps;
            let newConnection = opts.forceNew || opts['force new connection'] || false === opts.multiplex || sameNamespace;

            let io: Manager;

            if (newConnection) {
                io = new Manager(parsed, opts);
            } else {
                if (!this._cache[id]) {
                    this._cache[id] = new Manager(parsed, opts);
                }
                io = this._cache[id];
            }

            return io.socket(path, opts);
        }

        static getInstance(): IO {
            if (!this.instance) {
                this.instance = new IO();
            }
            return this.instance
        }
    }

    export interface SocketIOClientStatic {
        (uri?: Uri | string, opts?: Option): Socket;
        connect(uri?: Uri | string, opts?: Option): Socket;
    }

    export let SocketIOClientStatic = <SocketIOClientStatic>function (uri?: Uri | string, opts?: Option): Socket {
        return IO.getInstance().socket(uri, opts);
    };

    SocketIOClientStatic.prototype.connect = (uri?: Uri | string, opts?: Option): Socket => {
        return IO.getInstance().socket(uri, opts);
    }

    export let io = SocketIOClientStatic;
}

namespace SocketIOClient {
    export type Socket = egret.socketio.Socket;
    export type Manager = egret.socketio.Manager;
    export type Emitter = egret.socketio.Emitter;
}
